#include <tenacitas.translate.core/file_translator.h>
#include <tenacitas.return_code.core/rc.h>

#include <iostream>

#include "runtest.h"

namespace tenacitas { 
    namespace translate {
        namespace core {

            struct my_struct {
                static const class_id id = 142784768620556;

                enum ctes : constant_id { HELLO = 0, BYE = 1, HI = 2 };
            };
            const class_id my_struct::id;
            
            class file_translator_tester {

            private:

                struct cerr_media {

                    cerr_media(cerr_media &&) {}

                    cerr_media(const thread_id & p_thread_id)
                        : m_thread_id(p_thread_id){}
                    
                    rc<> new_line(level p_level,
                                  uint64_t p_nano,
                                  const char * p_file,
                                  int64_t p_line) {
                        std::cerr << "\n"
                                  << p_level.str() << "|"
                                  << p_nano << "|"
                                  << m_thread_id << "|"
                                  << p_file << "|"
                                  << p_line;
                        return rc<>();
                    }


                    template <typename t_data>
                    rc<> write(const t_data & p_data) {
                        std::cerr << "|" << p_data;
                        return rc<>();
                    }

                    template <typename t_data>
                    rc<> write( t_data && p_data) {
                        std::cerr << "|" << p_data;
                        return rc<>();
                    }

                    cerr_media & operator=(cerr_media && p_media) {
                        m_thread_id = std::move(p_media.m_thread_id);
                        return *this;
                    }

                private:
                    thread_id m_thread_id;
                };

                
                struct supplier_cerr {
                    typedef cerr_media media;
                    typedef log::core::logger<supplier_cerr> logger;
                };

                static const std::string m_translation_file;

                typedef core::file_translator<supplier_cerr> file_translator;
                
                
                static bool test1() {
                    std::cerr << "\n+++ file_translator_tester::test1" << std::endl;
                    file_translator::text_id l_text_id (1000,1);

                    return ( (l_text_id.m_class == 1000) &&
                             (l_text_id.m_constant == 1) ? true : false);
                }

                static bool test2() {
                    std::cerr << "\n+++ file_translator_tester::test2" << std::endl;
                    file_translator::text_id l_text_id (1000,1);

                    return ( (l_text_id.m_class != 100) &&
                             (l_text_id.m_constant != 10) ? true : false);
                }

                static bool test3() {
                    std::cerr << "\n+++ file_translator_tester::test3" << std::endl;
                    file_translator::text_id l_text_id (1000,1);

                    return ( (l_text_id.m_class != 100) &&
                             (l_text_id.m_constant == 1) ? true : false);
                }

                static bool test4() {
                    std::cerr << "\n+++ file_translator_tester::test4" << std::endl;
                    file_translator::text_id l_text_id (1000,1);

                    return ( (l_text_id.m_class == 1000) &&
                             (l_text_id.m_constant != 10) ? true : false);
                }

                static bool test5() {
                    std::cerr << "\n+++ file_translator_tester::test5" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,1);

                    file_translator::text_id l_text_id_2 (std::move(l_text_id_1));

                    return ( (l_text_id_2.m_class == 1000) &&
                             (l_text_id_2.m_constant == 1) ? true : false);
                }


                static bool test6() {
                    std::cerr << "\n+++ file_translator_tester::test6" << std::endl;
#if 0
                    // turn it on to test for compile error for using delete copy
                    // constructor 
                    file_translator::text_id l_text_id_1 (1000,1);

                    file_translator::text_id l_text_id_2 (l_text_id_1);

                    return (
                        (l_text_id_2.m_class == 1000) &&
                        (l_text_id_2.m_constant == 1) &&
                        (l_text_id_1.m_class == 1000) &&
                        (l_text_id_1.m_constant == 1) ? true : false);
#else
                    return true;
#endif
                }

                static bool test7() {
                    std::cerr << "\n+++ file_translator_tester::test7" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,1);

                    file_translator::text_id l_text_id_2 (1000,1);

                    return ( l_text_id_1 == l_text_id_2 ? true : false);
                }

                static bool test8() {
                    std::cerr << "\n+++ file_translator_tester::test8" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,2);

                    file_translator::text_id l_text_id_2 (1000,1);

                    return ( l_text_id_1 != l_text_id_2 ? true : false);
                }

                static bool test9() {
                    std::cerr << "\n+++ file_translator_tester::test9" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,2);

                    file_translator::text_id l_text_id_2 (1000,2);

                    return ( l_text_id_1 >= l_text_id_2 ? true : false);
                }

                static bool test10() {
                    std::cerr << "\n+++ file_translator_tester::test10" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,2);

                    file_translator::text_id l_text_id_2 (1000,1);

                    return ( l_text_id_1 >= l_text_id_2 ? true : false);
                }

                static bool test11() {
                    std::cerr << "\n+++ file_translator_tester::test11" << std::endl;
                    file_translator::text_id l_text_id_1 (1000,2);

                    file_translator::text_id l_text_id_2 (1000,3);

                    return ( l_text_id_1 >= l_text_id_2 ? false : true);
                }

                static bool test12() {
                    std::cerr << "\n+++ file_translator_tester::test12" << std::endl;
                    file_translator::text_id l_text_id_1 (230,2);

                    file_translator::text_id l_text_id_2 (1000,3);

                    return ( l_text_id_1 >= l_text_id_2 ? false : true);
                }

                static bool test13() {
                    std::cerr << "\n+++ file_translator_tester::test13" << std::endl;
                    file_translator::text_id l_text_id_1 (230,2);

                    file_translator::text_id l_text_id_2 (230,2);

                    return ( l_text_id_1 == l_text_id_2 ? true : false);
                }

                static bool test14() {
                    std::cerr << "\n+++ file_translator_tester::test14" << std::endl;
                    file_translator::text_id l_text_id_1 (230,2);

                    file_translator::text_id l_text_id_2 (231,2);

                    return ( l_text_id_1 == l_text_id_2 ? false : true);
                }

                static bool test15() {
                    std::cerr << "\n+++ file_translator_tester::test15" << std::endl;
                    file_translator::text_id l_text_id_1 (230,2);

                    file_translator::text_id l_text_id_2 (230,4);

                    return ( l_text_id_1 == l_text_id_2 ? false : true);
                }

                static bool test16() {
                    std::cerr << "\n+++ file_translator_tester::test16" << std::endl;
                    file_translator::text_id l_text_id_1 (235,4);

                    file_translator::text_id l_text_id_2 (230,4);

                    return ( l_text_id_1 != l_text_id_2 ? true : false);
                }

                static bool test17() {
                    std::cerr << "\n+++ file_translator_tester::test17" << std::endl;
                    file_translator::text_id l_text_id_1 (230,7);

                    file_translator::text_id l_text_id_2 (230,4);

                    return ( l_text_id_1 != l_text_id_2 ? true : false);
                }

                static bool test18() {
                    std::cerr << "\n+++ file_translator_tester::test18" << std::endl;
                    file_translator::text_id l_text_id_1 (231,7);

                    file_translator::text_id l_text_id_2 (230,9);

                    return ( l_text_id_1 > l_text_id_2 ? true : false);
                }

                static bool test19() {
                    std::cerr << "\n+++ file_translator_tester::test19" << std::endl;
                    file_translator::text_id l_text_id_1 (230,7);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 > l_text_id_2 ? true : false);
                }

                static bool test20() {
                    std::cerr << "\n+++ file_translator_tester::test20" << std::endl;
                    file_translator::text_id l_text_id_1 (230,1);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 > l_text_id_2 ? false : true);
                }

                static bool test21() {
                    std::cerr << "\n+++ file_translator_tester::test21" << std::endl;
                    file_translator::text_id l_text_id_1 (230,1);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 < l_text_id_2 ? true : false);
                }

                static bool test22() {
                    std::cerr << "\n+++ file_translator_tester::test22" << std::endl;
                    file_translator::text_id l_text_id_1 (230,3);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 < l_text_id_2 ? false : true);
                }

                static bool test23() {
                    std::cerr << "\n+++ file_translator_tester::test23" << std::endl;
                    file_translator::text_id l_text_id_1 (231,3);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 < l_text_id_2 ? false : true);
                }

                static bool test24() {
                    std::cerr << "\n+++ file_translator_tester::test24" << std::endl;
                    file_translator::text_id l_text_id_1 (230,3);

                    file_translator::text_id l_text_id_2 (230,3);

                    return ( l_text_id_1 <= l_text_id_2 ? true : false);
                }

                static bool test25() {
                    std::cerr << "\n+++ file_translator_tester::test25" << std::endl;
                    file_translator::text_id l_text_id_1 (230,3);

                    file_translator::text_id l_text_id_2 (231,3);

                    return ( l_text_id_1 <= l_text_id_2 ? true : false);
                }

                static bool test26() {
                    std::cerr << "\n+++ file_translator_tester::test26" << std::endl;
                    file_translator::text_id l_text_id_1 (230,3);

                    file_translator::text_id l_text_id_2 =
                        std::move(l_text_id_1);
                    

                    return ( ( (l_text_id_2.m_class == 230 ) &&
                               (l_text_id_2.m_constant == 3 ) ) ? true : false );
                }

                static bool test27() {
                    std::cerr << "\n+++ file_translator_tester::test27" << std::endl;
#if 0
                    // turn it on to test for compile error for using delete copy
                    // assignment
                    file_translator::text_id l_text_id_1 (1000,1);

                    file_translator::text_id l_text_id_2 = l_text_id_1;

                    return (
                        (l_text_id_2.m_class == 1000) &&
                        (l_text_id_2.m_constant == 1) &&
                        (l_text_id_1.m_class == 1000) &&
                        (l_text_id_1.m_constant == 1) ? true : false);
#else
                    return true;
#endif
                }

                static bool test28() {
                    std::cerr << "\n+++ file_translator_tester::test28" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add(m_translation_file);

                    supplier_cerr::logger _logger;                    
                    
                    if (!l_rc) {
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file "
                                           << m_translation_file;                        
                        return l_rc;
                    }

                    if (l_file_translator.size() != 3) {
                        return false;
                    }

                    l_file_translator.print(std::cerr);

                    std::string l_trans(l_file_translator(my_struct::id,
                                                          my_struct::HELLO));

                    std::cerr << "translation = '" << l_trans
                              << "'" << std::endl;
                    return true;
                }

                static bool test30() {
                    std::cerr << "\n+++ file_translator_tester::test30" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add(m_translation_file);

                    if (!l_rc) {
                        supplier_cerr::logger _logger;
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file "
                                           << m_translation_file;
                        
                        return l_rc;
                    }

                    l_file_translator.print(std::cerr);

                    std::string l_trans(l_file_translator(9992,
                                                          my_struct::HELLO));
                    std::cerr << l_trans << std::endl;
                    
                    return true;
                }

                static bool test31() {
                    std::cerr << "\n+++ file_translator_tester::test31" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add("bla.trans");
                    if (!l_rc) {
                        supplier_cerr::logger _logger;
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file 'bla.trans'";
                        

                        return true;
                    }
                    return false;
                }

                static bool test32() {
                    std::cerr << "\n+++ file_translator_tester::test32" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add(m_translation_file);

                    if (!l_rc) {
                        supplier_cerr::logger _logger;
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file "
                                           << m_translation_file;
                        
                        return l_rc;
                    }

                    l_file_translator.print(std::cerr);

                    std::string l_trans(l_file_translator(my_struct::id,
                                                          my_struct::HELLO));

                    std::cerr << "translation = '" << l_trans
                              << "'" << std::endl;
                        
                    return true;
                }

                static bool test33() {
                    std::cerr << "\n+++ file_translator_tester::test33" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add(m_translation_file);

                    if (!l_rc) {
                        supplier_cerr::logger _logger;
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file "
                                           << m_translation_file;
                        
                        return l_rc;
                    }

                    l_file_translator.print(std::cerr);

                    rc<float> _rc1(my_struct::id, my_struct::HELLO,
                                   __FILE__, __LINE__);
                    
                    std::string l_trans (l_file_translator(_rc1));

                    std::cerr << "translation = '" << l_trans
                              << "'" << std::endl;
                    return true;
                }

                static bool test34() {
                    std::cerr << "\n+++ file_translator_tester::test34" << std::endl;
                    file_translator l_file_translator;

                    rc<> l_rc = l_file_translator.add(m_translation_file);

                    if (!l_rc) {
                        supplier_cerr::logger _logger;
                        log_error(_logger) << "error : " << l_rc.get_class_id()
                                           << ", " << l_rc.get_constant_id()
                                           << ", for file "
                                           << m_translation_file;
                        
                        return l_rc;
                    }

                    l_file_translator.print(std::cerr);

                    rc<float> _rc1(3754, 2, __FILE__, __LINE__);
                    
                    std::string l_trans (l_file_translator(_rc1));

                    std::cerr << "\ntranslation = '" << l_trans
                              << "'" << std::endl;
                    return true;
                }
                

            public:
                static void run() {
                    runtest(file_translator_tester::test1());
                    runtest(file_translator_tester::test2());
                    runtest(file_translator_tester::test3());
                    runtest(file_translator_tester::test4());
                    runtest(file_translator_tester::test5());
                    runtest(file_translator_tester::test6());
                    runtest(file_translator_tester::test7());
                    runtest(file_translator_tester::test8());
                    runtest(file_translator_tester::test9());
                    runtest(file_translator_tester::test10());
                    runtest(file_translator_tester::test11());
                    runtest(file_translator_tester::test12());
                    runtest(file_translator_tester::test13());
                    runtest(file_translator_tester::test14());
                    runtest(file_translator_tester::test15());
                    runtest(file_translator_tester::test16());
                    runtest(file_translator_tester::test17());
                    runtest(file_translator_tester::test18());
                    runtest(file_translator_tester::test19());
                    runtest(file_translator_tester::test20());
                    runtest(file_translator_tester::test21());
                    runtest(file_translator_tester::test22());
                    runtest(file_translator_tester::test23());
                    runtest(file_translator_tester::test24());
                    runtest(file_translator_tester::test25());
                    runtest(file_translator_tester::test26());
                    runtest(file_translator_tester::test27());
                    runtest(file_translator_tester::test28());
                    runtest(file_translator_tester::test30());
                    runtest(file_translator_tester::test31());
                    runtest(file_translator_tester::test32());
                    runtest(file_translator_tester::test33());
                    runtest(file_translator_tester::test34());
                }

                
            };
            const std::string
            file_translator_tester::
            m_translation_file(std::string(DIR_TEST) +
                               std::string("/my_struct_pt-BR.trans")); 

        }
    }
}
